/**
 * 工具类
 * 提供系统时间获取、文件路径操作等功能
 */
#ifndef UTIL_H
#define UTIL_H
#include <iostream>
#include <sstream>
#include <fstream>
#include <ctime>
#include <sys/stat.h>
#include <sys/types.h>

namespace Log
{
    namespace util
    {
        /**
         * @brief 日期时间工具类
         * 提供系统时间相关操作
         */
        class Date
        {
        public:
            /**
             * @brief 获取当前系统时间的秒数（自Epoch起）
             * @return size_t 当前时间戳的秒数表示
             */
            static size_t getTime()
            {
                return (size_t)time(nullptr);
            }
        };

        /**
         * @brief 文件操作工具类
         * 提供文件路径处理、目录创建等功能
         */
        class File
        {
        public:
            /**
             * @brief 检查指定路径的文件或目录是否存在
             * @param pathName 要检查的路径字符串
             * @return bool true-路径存在，false-路径不存在
             */
            static bool exists(const std::string &pathName)
            {
                struct stat st;
                return !stat(pathName.c_str(), &st);
            }

            /**
             * @brief 从完整路径中提取目录部分
             * @param pathName 完整文件路径字符串
             * @return std::string 包含末尾分隔符的目录路径
             * @note 如果路径中没有分隔符，返回"."表示当前目录
             * @example
             *  输入 "/var/log/app.log" 返回 "/var/log/"
             *  输入 "config.ini" 返回 "."
             */
            static std::string path(const std::string &pathName)
            {
                size_t pos = pathName.find_last_of("/\\");
                return pos == std::string::npos ? "." : pathName.substr(0, pos + 1);
            }

            /**
             * @brief 递归创建目录结构
             * @param pathName 要创建的目录路径
             * @throw std::system_error 当目录创建失败时抛出，包含错误码和描述
             * @note 支持创建多级目录，自动跳过已存在的目录
             * @example
             *  输入 "logs/2023/08" 会依次创建logs/, logs/2023/, logs/2023/08/
             */
            static void createDirectory(const std::string &pathName)
            {
                size_t pos = 0;
                size_t index = 0;
                while (index < pathName.size())
                {
                    pos = pathName.find_first_of("/\\", index);
                    if (pos == std::string::npos)
                    {
                        if (!exists(pathName))
                        {
                            if (mkdir(pathName.c_str(), 0777) != 0)
                            {
                                throw std::system_error(errno, std::generic_category(), "Failed to create directory");
                            }
                        }
                        return;
                    }

                    std::string parent_dir = pathName.substr(0, pos);
                    if (!parent_dir.empty() && !exists(parent_dir))
                    {
                        if (mkdir(parent_dir.c_str(), 0777) != 0)
                        {
                            throw std::system_error(errno, std::generic_category(), "Failed to create directory");
                        }
                    }

                    index = pos + 1;
                }
            }

            /**
             * @brief 获取文件实际大小
             * @param pathname 文件路径
             * @return 文件大小（字节）
             * @throw std::runtime_error 当文件访问失败时抛出
             *
             * 使用文件系统库或系统调用获取文件大小，确保准确性。
             */
            static size_t getFileSize(const std::string &pathname)
            {
                std::ifstream file(pathname, std::ios::binary | std::ios::ate);
                if (!file)
                {
                    throw std::runtime_error("Failed to open file for size check: " + pathname);
                }
                return file.tellg();
            }
        };
    }
}

#endif